package jp.tkym.labs.geom;

import java.util.HashMap;
import java.util.Map;


public class CoordinateModel {
	public final Coordinate3f coordinate;
	private final String name;
	private final Map<String, CoordinateModel> childlen;
	
	private CoordinateModel parent;
	
	public CoordinateModel(String name){
		this.name = name;
		this.parent = null;
		childlen = new HashMap<String, CoordinateModel>();
		this.coordinate = new Coordinate3f();
	}
	
	public void add(CoordinateModel model){
		childlen.put(model.name, model);
		model.parent = this;
	}
	
	public void remove(String name){
		CoordinateModel child = childlen.get(name);
		if(child == null) throw new IllegalArgumentException("name "+name + " is not exited");
		childlen.remove(name);
		child.parent = null;
	}
	
	public CoordinateModel get(String... name){
		if(name.length == 0) return this;
		CoordinateModel child = childlen.get(name[0]);
		if(child == null)  throw new IllegalArgumentException("name "+name[0]+" is not existed ");
		String[] next = new String[name.length-1];
		for(int i=0; i<next.length; i++) next[i] = name[i+1];
		return child.get(next);
	}
	
	private Vector3f translateForwordOnWorld(Vector3f p){
		Vector3f r = this.coordinate.translate(p);
		if(this.parent == null) return r;
		return this.parent.translateForwordOnWorld(r);
	}
	
	private Vector3f translateInverseOnWorld(Vector3f p){
		Vector3f r = p;
		if(this.parent != null)
			r = this.parent.translateInverseOnWorld(p);
		return this.coordinate.inverseTranslate(r);
	}
	
	public CoordinateTranslator onView(CoordinateModel coordinateModel){
		return new CoordinateTranslator(coordinateModel, this);
	}
	
	public CoordinateTranslator onWorld(){
		return new CoordinateTranslator(this);
	}
	
	public class CoordinateTranslator{
		final CoordinateModel view;
		final CoordinateModel target;
		
		CoordinateTranslator(CoordinateModel target){
			this.view = null;
			this.target = target;
		}
		
		CoordinateTranslator(CoordinateModel view, CoordinateModel target){
			this.view = view;
			this.target = target;
		}
		
		public Vector3f translate(Vector3f p){
			Vector3f onWorld = target.translateForwordOnWorld(p);
			if(view == null) return onWorld;
			else return view.translateInverseOnWorld(onWorld);
		}
	}
}